{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"color:#777777;background-color:#ffffff;font-size:12px;text-align:right;\">\n",
    "\tprepared by Abuzer Yakaryilmaz (QuSoft@Riga) | November 07, 2018\n",
    "</div>\n",
    "<table><tr><td><i> I have some macros here. If there is a problem with displaying mathematical formulas, please run me to load these macros.</i></td></td></table>\n",
    "$ \\newcommand{\\bra}[1]{\\langle #1|} $\n",
    "$ \\newcommand{\\ket}[1]{|#1\\rangle} $\n",
    "$ \\newcommand{\\braket}[2]{\\langle #1|#2\\rangle} $\n",
    "$ \\newcommand{\\inner}[2]{\\langle #1,#2\\rangle} $\n",
    "$ \\newcommand{\\biginner}[2]{\\left\\langle #1,#2\\right\\rangle} $\n",
    "$ \\newcommand{\\mymatrix}[2]{\\left( \\begin{array}{#1} #2\\end{array} \\right)} $\n",
    "$ \\newcommand{\\myvector}[1]{\\mymatrix{c}{#1}} $\n",
    "$ \\newcommand{\\myrvector}[1]{\\mymatrix{r}{#1}} $\n",
    "$ \\newcommand{\\mypar}[1]{\\left( #1 \\right)} $\n",
    "$ \\newcommand{\\mybigpar}[1]{ \\Big( #1 \\Big)} $\n",
    "$ \\newcommand{\\sqrttwo}{\\frac{1}{\\sqrt{2}}} $\n",
    "$ \\newcommand{\\dsqrttwo}{\\dfrac{1}{\\sqrt{2}}} $\n",
    "$ \\newcommand{\\onehalf}{\\frac{1}{2}} $\n",
    "$ \\newcommand{\\donehalf}{\\dfrac{1}{2}} $\n",
    "$ \\newcommand{\\hadamard}{ \\mymatrix{rr}{ \\sqrttwo & \\sqrttwo \\\\ \\sqrttwo & -\\sqrttwo }} $\n",
    "$ \\newcommand{\\vzero}{\\myvector{1\\\\0}} $\n",
    "$ \\newcommand{\\vone}{\\myvector{0\\\\1}} $\n",
    "$ \\newcommand{\\vhadamardzero}{\\myvector{ \\sqrttwo \\\\  \\sqrttwo } } $\n",
    "$ \\newcommand{\\vhadamardone}{ \\myrvector{ \\sqrttwo \\\\ -\\sqrttwo } } $\n",
    "$ \\newcommand{\\myarray}[2]{ \\begin{array}{#1}#2\\end{array}} $\n",
    "$ \\newcommand{\\X}{ \\mymatrix{cc}{0 & 1 \\\\ 1 & 0}  } $\n",
    "$ \\newcommand{\\Z}{ \\mymatrix{rr}{1 & 0 \\\\ 0 & -1}  } $\n",
    "$ \\newcommand{\\Htwo}{ \\mymatrix{rrrr}{ \\frac{1}{2} & \\frac{1}{2} & \\frac{1}{2} & \\frac{1}{2} \\\\ \\frac{1}{2} & -\\frac{1}{2} & \\frac{1}{2} & -\\frac{1}{2} \\\\ \\frac{1}{2} & \\frac{1}{2} & -\\frac{1}{2} & -\\frac{1}{2} \\\\ \\frac{1}{2} & -\\frac{1}{2} & -\\frac{1}{2} & \\frac{1}{2} } } $\n",
    "$ \\newcommand{\\CNOT}{ \\mymatrix{cccc}{1 & 0 & 0 & 0 \\\\ 0 & 1 & 0 & 0 \\\\ 0 & 0 & 0 & 1 \\\\ 0 & 0 & 1 & 0} } $\n",
    "$ \\newcommand{\\norm}[1]{ \\left\\lVert #1 \\right\\rVert } $"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2>Rotations</h2>\n",
    "\n",
    "We have a single qubit. \n",
    "\n",
    "Each quantum state of a qubit is a 2-dimensional vector.\n",
    "\n",
    "Which geometric object do all quantum states (real-valued) of a qubit form?\n",
    "\n",
    "We can randomly pick 100 quantum states, and put a point for each of them on 2-dimensional space. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from random import randrange\n",
    "\n",
    "# randomly create a 2-dimensional quantum state\n",
    "def random_quantum_state():\n",
    "    first_entry = randrange(100)\n",
    "    first_entry = first_entry/100\n",
    "    first_entry = first_entry**0.5 # we found the first value before determining its sign\n",
    "    if randrange(2) == 0: \n",
    "        first_entry = -1 * first_entry\n",
    "    second_entry = 1 - (first_entry**2)\n",
    "    second_entry = second_entry**0.5\n",
    "    if randrange(2) == 0: \n",
    "        second_entry = -1 * second_entry\n",
    "    return [first_entry,second_entry]\n",
    "\n",
    "from matplotlib.pyplot import plot, show, figure # import the useful tool for drawing figures in python\n",
    "\n",
    "figure(figsize=(6,6), dpi=60) # size of the figure\n",
    "\n",
    "plot(0,0,'bo') # point the origin (0,0)\n",
    "\n",
    "for i in range(100):\n",
    "    quantum_state = random_quantum_state(); # random quantum state\n",
    "    plot(quantum_state[0],quantum_state[1],'bo') # put a point for the quantum state\n",
    "\n",
    "show() # show the diagram"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3> Unit circle </h3>\n",
    "\n",
    "All quantum states of a qubit form the unit circle.\n",
    "\n",
    "The length of each quantum state is 1.\n",
    "\n",
    "All points that are 1 unit away from the origin form the circle with radius 1 unit.\n",
    "\n",
    "We can draw it with python."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# import the useful tool for drawing figures in python\n",
    "from matplotlib.pyplot import plot, show, figure, Circle, axis, gca, annotate, arrow, text\n",
    "\n",
    "\n",
    "figure(figsize=(6,6), dpi=80) # size of the figure\n",
    "\n",
    "gca().add_patch( Circle((0,0),1,color='black',fill=False) ) # define a circle\n",
    "\n",
    "plot(-1.3,0)\n",
    "plot(1.3,0)\n",
    "plot(0,1.3)\n",
    "plot(0,-1.3)\n",
    "\n",
    "# axes\n",
    "arrow(0,0,1.1,0,head_width=0.04, head_length=0.08)\n",
    "arrow(0,0,-1.1,0,head_width=0.04, head_length=0.08)\n",
    "arrow(0,0,0,-1.1,head_width=0.04, head_length=0.08)\n",
    "arrow(0,0,0,1.1,head_width=0.04, head_length=0.08)\n",
    "\n",
    "show() # show the diagram"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3> Quantum operators on the unit circle </h3>\n",
    "\n",
    "A quantum operator preserves the length of the given vector. \n",
    "\n",
    "There are two types of operators defined on the unit circle: <b>Rotations</b> and <b>Reflections</b>.\n",
    "\n",
    "A rotation is defined with its angle. \n",
    "\n",
    "A full rotation is 360 degrees. \n",
    "\n",
    "It is also represented as $ 2 \\pi $, the length (circumference) of the unit circle.\n",
    "\n",
    "In scientific calculations, the second representation is more commonly used."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3> Rotations with ry-gate </h3>\n",
    "\n",
    "The ry-gate is used for rotation in 2-dimensional real-valued plane.\n",
    "\n",
    "If our angle is $ \\theta $, then we pass $ 2 \\theta $ to ry-gate (due to a technical reason).\n",
    "\n",
    "Then ry-gate exactly implements the rotation with angle $\\theta$. \n",
    "\n",
    "The default direction of a rotation by ry-gate is counterclockwise."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3> Python function for rotations </h3>\n",
    "\n",
    "We write a python function to implement the rotations, and then visualize the resulting quantum states.\n",
    "\n",
    "It takes two parameters: rotation_angle and number_of_rotations\n",
    "\n",
    "We start in state $ \\ket{0} $. \n",
    "\n",
    "Then, we implement the rotation specified times with the specified angle.\n",
    "\n",
    "After each rotation, we visualize the resulting quantum state.\n",
    "\n",
    "<i>Please do not forget to execute our function before using it.</i>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def rotations(rotation_angle,number_of_rotations):\n",
    "    # import all necessary objects and methods for quantum circuits\n",
    "    from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, execute, Aer\n",
    "    from qiskit.tools.visualization import matplotlib_circuit_drawer as drawer\n",
    "    # import the useful tool for drawing figures in python\n",
    "    from matplotlib.pyplot import plot, show, figure, Circle, axis, gca, annotate, arrow, text\n",
    "    # import the constant pi\n",
    "    from math import pi\n",
    "    \n",
    "    # we define a quantum circuit with one qubit and one bit\n",
    "    qreg1 =  QuantumRegister(1) # quantum register with a single qubit\n",
    "    creg1 = ClassicalRegister(1) # classical register with a single bit\n",
    "    mycircuit1 = QuantumCircuit(qreg1,creg1) # quantum circuit with quantum and classical registers\n",
    "\n",
    "    # create the plane\n",
    "    figure(figsize=(6,6), dpi=80) # size of the figure\n",
    "    gca().add_patch( Circle((0,0),1,color='black',fill=False) ) # draw the circle\n",
    "    # auxiliary points\n",
    "    plot(-1.3,0)\n",
    "    plot(1.3,0)\n",
    "    plot(0,1.3)\n",
    "    plot(0,-1.3)\n",
    "    # axes\n",
    "    arrow(0,0,1.1,0,head_width=0.04, head_length=0.08)\n",
    "    arrow(0,0,-1.1,0,head_width=0.04, head_length=0.08)\n",
    "    arrow(0,0,0,-1.1,head_width=0.04, head_length=0.08)\n",
    "    arrow(0,0,0,1.1,head_width=0.04, head_length=0.08)\n",
    "    # end of create the plane\n",
    "\n",
    "    for i in range(number_of_rotations):\n",
    "        # iteratively apply the rotation \n",
    "        mycircuit1.ry(2*rotation_angle,qreg1[0]) \n",
    "        \n",
    "        # the following code is used to get the quantum state of the quantum register\n",
    "        job = execute(mycircuit1,Aer.get_backend('statevector_simulator'))\n",
    "        current_quantum_state=job.result().get_statevector(mycircuit1) \n",
    "        x_value = current_quantum_state[0].real # get the amplitude of |0>\n",
    "        y_value = current_quantum_state[1].real # get the amplitude of |1>\n",
    "        # show the quantum state as an arrow on the diagram\n",
    "        arrow(0,0,x_value,y_value,head_width=0.04, head_length=0.08,color='blue')\n",
    "\n",
    "        # the following code is used to indicate the rotation number\n",
    "        if x_value<0: text_x_value=x_value-0.1\n",
    "        else: text_x_value=x_value+0.1\n",
    "        if y_value<0: text_y_value=y_value-0.1\n",
    "        else: text_y_value=y_value+0.1        \n",
    "        text(text_x_value,text_y_value,'r='+str(i+1))\n",
    "    # end of for-loop\n",
    "    show() # show the diagram\n",
    "#end of function\n",
    "\n",
    "print(\"function 'rotations' is defined now, and so it can be used in the following part\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3> Test the function <font color=\"blue\">rotations</font> </h3>\n",
    "\n",
    "Let's rotate the state $ \\ket{0} $ with angle pi/4 8 times."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# call function rotations 8 times with angle pi/4\n",
    "\n",
    "# import the constant pi\n",
    "from math import pi\n",
    "    \n",
    "rotations(pi/4,8)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3> Task 1 </h3>\n",
    "\n",
    "Call function rotations with respect to the following scenarios."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h4> Scenario 1 </h4>\n",
    "\n",
    "rotation_angle = pi/4\n",
    "<br> \n",
    "number_of_rotations = 16\n",
    "\n",
    "The same quantum states should be visited twice."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#\n",
    "# your code is here\n",
    "#\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h4> Scenario 2 </h4>\n",
    "\n",
    "rotation_angle = pi/8\n",
    "<br> \n",
    "number_of_rotations = 16\n",
    "\n",
    "Compared to pi/4, more quantum states should be visited on the unit circle."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#\n",
    "# your code is here\n",
    "#\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h4> Scenario 3 </h4>\n",
    "\n",
    "rotation_angle = 3*pi/8\n",
    "<br> \n",
    "number_of_rotations = 16\n",
    "\n",
    "The same states should be visited but in different order."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#\n",
    "# your code is here\n",
    "#\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h4> Scenario 4 </h4>\n",
    "\n",
    "rotation_angle = pi\\*(2**0.5)\n",
    "<br> \n",
    "number_of_rotations = 16\n",
    "\n",
    "The angle is an irrational multiple of pi. So, the same quantum state should not be visited."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#\n",
    "# your code is here\n",
    "#\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h4> Scenario 5 </h4>\n",
    "\n",
    "Let's repeat Scenario 4 with more rotations.\n",
    "\n",
    "rotation_angle = pi\\*(2**0.5)\n",
    "<br> \n",
    "number_of_rotations = 32 and then 64"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#\n",
    "# your code is here\n",
    "#\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h4> Scenario 6 </h4>\n",
    "\n",
    "Create your own scenario (!)\n",
    "\n",
    "rotation_angle = pi*\n",
    "<br> \n",
    "number_of_rotations = "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#\n",
    "# your code is here\n",
    "#\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3> Preserving the angles </h3>\n",
    "\n",
    "Any quantum state on the unit circle can be specified by its angle with $x$-axis.\n",
    "\n",
    "Then, we define $ \\ket{u_1} $ and $ \\ket{u_2} $ as two quantum states with angles $ \\theta_1 $ and $ \\theta_2 $.\n",
    "\n",
    "The angle between two quantum states is $ \\theta_1 - \\theta_2 $.\n",
    "\n",
    "If we apply a rotation with angle $ \\theta $ to the both quantum states, then the new quantum states will have the angles of $ \\theta_1 + \\theta $ and $ \\theta_2 + \\theta $.\n",
    "\n",
    "It is easy to see that a rotation preserves the angle between two quantum states ($ \\theta_1 - \\theta_2 $ in our example)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3> Separability of orthogonal quantum states </h3>\n",
    "\n",
    "Suppose that $ \\theta_1 - \\theta_2 = \\frac{\\pi}{4} $ (90 degrees) in the above example.\n",
    "\n",
    "($ \\ket{u_1} $ and $ \\ket{u_2} $ are said to be orthogonal (perpendicular) to each other.)\n",
    "\n",
    "Then, there is a rotation with angle $ \\theta = -\\theta_2 $. \n",
    "\n",
    "If this rotation is applied to $ \\ket{u_1} $ and $ \\ket{u_2} $, the resulting quantum states will have the angles of $ \\theta_1 + (-\\theta_2) = \\frac{\\pi}{4} $ and $ \\theta_2 + (-\\theta_1) = 0 $, respectively.\n",
    "\n",
    "The resulting quantum states are $ \\ket{1} $ and $ \\ket{0} $. \n",
    "\n",
    "So, when we measure each of them, we get a different result with probability 1.\n",
    "\n",
    "Thus, $ \\ket{u_1} $ and $ \\ket{u_2} $ are perfectly separable.\n",
    "\n",
    "This fact is true for any two orthogonal quantum states."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
